﻿#pragma once

#include <xy/ais/arrow.h>
#include <xy/ais/curve.h>
#include <xy/ais/mesh.h>
#include <xy/ais/point.h>
#include <xy/ais/surface.h>

using namespace xy::ais;
using namespace xy::geom;

// 前向声明
class Context;

class Renderer : public renderer
{
  protected:
    int m_id;
    Context *m_ctx;

    /**
     * @brief ID 生成器
     *
     * @return int
     */
    static int _gen_id() noexcept;

  public:
    /**
     * @brief 默认构造函数
     *
     * @param[in] ctx
     */
    Renderer(Context *ctx);

    /**
     * @brief 重载默认析构函数
     *
     */
    virtual ~Renderer();

    /**
     * @brief 更新基准 uniform 变量
     *
     * @param[in] obj
     */
    void update_uniform(const object *obj) const;

  public:
    float basicOpacity{1.0f};
    float hoveredOpacity{0.6f};
    float pressedOpacity{0.8f};
};

class PointRenderer : public Renderer
{
  public:
    /**
     * @brief 单点渲染器构造函数
     *
     * @param[in] ctx
     */
    PointRenderer(Context *ctx);

    /**
     * @brief 刷新渲染器
     *
     * @param[in] obj
     */
    void update(const object *obj) override;

    /**
     * @brief 绘制物体
     *
     * @param[in] obj
     */
    void draw(const object *obj) const override;

  public:
    vec3f basicColor{1.0f, 1.0f, 1.0f};
    vec3f hoveredColor{1.0f, 1.0f, 0.0f};
    vec3f pressedColor{1.0f, 1.0f, 0.0f};
    float basicSize{5.0f};
    float hoveredSize{8.0f};
    float pressedSize{6.0f};
};

class CurveRenderer : public Renderer
{
  public:
    /**
     * @brief 曲线渲染器构造函数
     *
     * @param[in] ctx
     */
    CurveRenderer(Context *ctx);

    /**
     * @brief 刷新渲染器
     *
     * @param[in] obj
     */
    void update(const object *obj) override;

    /**
     * @brief 绘制物体
     *
     * @param[in] obj
     */
    void draw(const object *obj) const override;

  public:
    std::size_t sampleCount{100};
    vec3f basicColor{1.0f, 1.0f, 1.0f};
    vec3f hoveredColor{0.0f, 1.0f, 0.0f};
    vec3f pressedColor{0.0f, 1.0f, 0.0f};
    float basicWidth{2.0f};
    float hoveredWidth{4.0f};
    float pressedWidth{3.0f};
};

class ArrowRenderer : public Renderer
{
  public:
    /**
     * @brief 向量渲染器构造函数
     *
     * @param[in] ctx
     */
    ArrowRenderer(Context *ctx);

    /**
     * @brief 刷新渲染器
     *
     * @param[in] obj
     */
    void update(const object *obj) override;

    /**
     * @brief 绘制物体
     *
     * @param[in] obj
     */
    void draw(const object *obj) const override;
};

class MeshRenderer : public Renderer
{
  public:
    /**
     * @brief 网格渲染器构造函数
     *
     * @param[in] ctx
     */
    MeshRenderer(Context *ctx);

    /**
     * @brief 刷新渲染器
     *
     * @param[in] obj
     */
    void update(const object *obj) override;

    /**
     * @brief 绘制物体
     *
     * @param[in] obj
     */
    void draw(const object *obj) const override;

  public:
    vec3f direction{0.0f, 0.0f, -1.0f}; // 光线方向
    vec3f ambient{0.1f, 0.1f, 0.1f};    // 环境光
    vec3f diffuse{0.8f, 0.8f, 0.8f};    // 漫反射
    vec3f specular{0.8f, 0.8f, 0.8f};   // 镜面反射
    int zebra{0};                       // 斑马纹密度
    unsigned int diffuseTex;            // 散射纹理
    unsigned int specularTex;           // 镜面纹理
    unsigned int reflectTex;            // 反射纹理
    unsigned int reflactTex;            // 折射纹理

  protected:
    std::size_t m_count; // 记录网格顶点数量
};

class SurfaceRenderer : public MeshRenderer
{
  public:
    /**
     * @brief 曲面渲染器构造函数
     *
     * @param[in] ctx
     */
    SurfaceRenderer(Context *ctx);

    /**
     * @brief 刷新渲染器
     *
     * @param[in] obj
     */
    void update(const object *obj) override;

  public:
    std::size_t sampleCount{30};
};